/*
 * Copyright (c) $today.year-Now http://www.zxpnet.com All rights reserved.
 */

package com.zxp.security.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zxp.common.core.security.authentication.MobileAuthenticationSecurityConfig;
import com.zxp.common.core.security.authentication.handler.MyAuthenticationSuccessHandler;
import com.zxp.common.core.security.filter.ValidateCodeFilter;
import com.zxp.common.core.security.properties.SecurityProperties;
import com.zxp.common.core.validatecode.impl.ImageValidateCodeService;
import com.zxp.common.core.validatecode.impl.SmsValidateCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.sql.DataSource;

/**
 *  继承WebSecurityConfigurerAdapter
 * @author: shollin
 * @date: 2021/7/3/003 17:13
 */
@Configuration
@RequiredArgsConstructor
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    private final PasswordEncoder passwordEncoder;
    private final DataSource dataSource;
    private final UserDetailsService userDetailsService;
    private final RedisTemplate<String,Object> redisTemplate;
    private final SecurityProperties securityProperties;
    private final ImageValidateCodeService imageValidateCodeService;
    private final SmsValidateCodeService smsValidateCodeService;
    private final ValidateCodeFilter validateCodeFilter;

    private final AuthenticationFailureHandler authenticationFailureHandler;
    private final PersistentTokenRepository rememberMeTokenRepository;

    private final ObjectMapper objectMapper;
    private final ClientDetailsService clientDetailsService;


    /**
     * 用户配置： 从内存中获取 auth.inMemoryAuthentication()..withUser("root").password(passwordEncoder.encode("123")).roles("ADMIN", "DBA")
     *
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);

    }


    /*@Override
    @Bean
    protected UserDetailsService userDetailsService() {
        //InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();

        // 切换用户数据来源于数据库: jdbc   user.ddl
        JdbcUserDetailsManager userDetailsManager = new JdbcUserDetailsManager(dataSource);

        if(!userDetailsManager.userExists("admin")){
            userDetailsManager.createUser(User.withUsername("root").password(passwordEncoder.encode("123")).roles("ADMIN", "DBA").build());
            userDetailsManager.createUser(User.withUsername("admin").password(passwordEncoder.encode("123")).roles("ADMIN").build());
            userDetailsManager.createUser(User.withUsername("user").password(passwordEncoder.encode("123")).roles("USER").build());
        }
        return userDetailsManager;
    }*/

    // 角色继承
    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); // admin角色拥有user角色的权限
        return hierarchy;
    }

    /**
     * 要放行的资源，不走 Spring Security 过滤器链， 因此不要把/login放行     *
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers(HttpMethod.OPTIONS, "/**")
                .antMatchers("/favicon.ico")
                .antMatchers("/error","/code/*")
                .antMatchers("/static/**", "/images/**", "/css/**", "/assets/**")
                .antMatchers("/webjars*", "/webjars/**")
                .antMatchers("/swagger-resources/**", "/swagger-ui/**", "/v2/**", "/doc.html", "/swagger-ui.html")
                .antMatchers("/test/**")
                .antMatchers("/excel/**")
                .antMatchers("/upload/**");
    }

    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}
